package yxy.apple.http.server.business;

import java.util.HashMap;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import lombok.extern.slf4j.Slf4j;
import yxy.apple.util.ReflectionUtility;

@Slf4j
public class RequestDispatcher {

	static private RequestDispatcher instance;

	public static RequestDispatcher getInstance() {
		if (instance == null) {
			instance = new RequestDispatcher();
		}
		return instance;
	}

	private RequestConverter converter;

	private HashMap<String, Adapter> adapters = new HashMap<>();

	public void setConverter(RequestConverter converter) {
		this.converter = converter;
	}

	public void initAdapter(String packageName) throws Exception {
//		Set<Class<? extends Business>> businessTypes = ReflectionUtility.getSubTypesOf(packageName, Business.class);
//		for (Class<? extends Business> clazz : businessTypes) {
//			Business business = (Business) clazz.getConstructor().newInstance();
//			String adapterCode = business.adapter();
//			if (!adapters.containsKey(adapterCode)) {
//				adapters.put(adapterCode, new Adapter(adapterCode));
//			}
//			adapters.get(adapterCode).add(business);
//		}

		Set<Class<?>> businessTypes = ReflectionUtility.getTypesAnnotatedWith(packageName, BusinessType.class);
		log.info("businessTypes {}", JSON.toJSONString(businessTypes));
		for (Class<?> clazz : businessTypes) {
			String adapterCode = clazz.getAnnotation(BusinessType.class).code();
			Business business = (Business) clazz.getConstructor().newInstance();
			if (!adapters.containsKey(adapterCode)) {
				adapters.put(adapterCode, new Adapter(adapterCode));
			}
			adapters.get(adapterCode).add(business);
		}
		log.info("adapters {}", JSON.toJSONString(adapters));
	}

	public JSONObject service(String requestPath, JSONObject content) {
		log.info("service {}, {}", requestPath, JSON.toJSONString(content));
		String code = this.converter.convert(requestPath);
		Adapter adapter = adapters.get(code);
		String businessName = content.getString("business");
		log.info("businessName {}", businessName);
		return adapter.adapte(businessName, content);
	}

	private class Adapter {

		private String code;

		private Adapter(String code) {
			this.code = code;
		}

		private String getCode() {
			return code;
		}

		private ConcurrentHashMap<String, Business> businessMap = new ConcurrentHashMap<>();

		private void add(Business business) {
			if (businessMap.containsKey(business.name())) {
				log.error("Business");
			}
			businessMap.put(business.name(), business);
		}

		private JSONObject adapte(String name, JSONObject content) {
			try {
				System.out.println("adapte name : " + name);
				System.out.println("businessMap : " + JSON.toJSONString(businessMap));
				Business business = businessMap.get(name);
				//重复调用，导致登录login等接口被调用两次
				//business.clone().handle(content);
				return business.clone().handle(content);
			} catch (Exception e) {
				e.printStackTrace();
				JSONObject result = new JSONObject();
				result.put("result", "error");
				return result;
			}
		}

	}

}
